package com.blackcat.rabbitmq.config;

import com.alibaba.fastjson.JSON;
import com.blackcat.rabbitmq.entity.Simple;
import com.blackcat.rabbitmq.message.RabbitData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.UUID;

/**
 * 描述 ：生产者
 *  生产者需要用到 RabbitTemplate 类来生产消息并进行消息发送
 * @author : zhangdahui
 * @date : 2022/8/15 10:33
 * @link https://www.rabbitmq.com/getstarted.html 官网教程
 */
@Slf4j
@Component
public class Producer {

//    @Resource(name = "rabbit")
//    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 简单队列模式  发送简单消息
     * 角色:一个生产者、一个队列、一个消费者;
     * 流程:生产者向队列里发送消息，消费者从队列中获取消息并消费。
     **/
    public void produce() {
        String message = "发出消息";
        System.out.println("生产者：" + message);
        rabbitTemplate.convertAndSend("notice_queue", message);
    }

    /**
     * 简单队列模式  发送对象
     * 角色:一个生产者、一个队列、一个消费者;
     * 流程:生产者向队列里发送消息，消费者从队列中获取消息并消费。
     **/
    public void simple(){
        // 创建一个对象
        Simple simple = new Simple();
        simple.setName("zhangsan");
        simple.setAge(11);
        simple.setCreateTime(new Date());
        simple.setPhone("1234555");
        simple.setNo("0001");
        // 转换发送商品信息
        System.out.println("创建" + simple.getName() + "对象，发送通知");
        rabbitTemplate.convertAndSend("notice_user_queue", simple);
    }

    /**
     * 工作队列模式
     * 角色:一个生产者、一个队列、多个消费者;
     * 流程:两个消费者同时绑定到一个队列上去，当消费者获取消息处理耗时任务时，空闲的消费者从队列中获取并消费消息。
     * 注：多个费者是通过轮询来分配消息，而且每个消息只能消费一次
     **/
    public void work(){
        String message = "工作队列模式";
        System.out.println("生产者：" + message);
        rabbitTemplate.convertAndSend("work_queue", message);
    }

    /**
     * 发布/订阅模式
     * 角色:一个生产者、多个队列、多个消费者、一个交换机;
     * 流程:两个消费者同时绑定到不同的队列上去，两个队列绑定到交换机上去，
     *      生产者通过发送消息到交换机，所有消费者接收并消费消息。
     **/
    public void push(){
        String message = "发布/订阅模式";
        System.out.println("生产者：" + message);
        // 生产者发布消息到交换机
        //参数
        // 1、交换机名称
        // 2、路由key 由于我们实现的是fanout模式（广播模式），不需要路由key，所有的消费者都可以进行监听和消费
        // 3、发送mq消息
        rabbitTemplate.convertAndSend("fanout-order-exchange","" ,message);
    }

    /**
     * 路由模式
     * 角色:一个生产者、多个消费者、多个队列、一个交换机;
     * 流程:两个消费者同时绑定到不同的队列上去，两个队列通过路由键绑定到交换机上去，
     *      生产者发送消息到交换机，交换机通过路由键转发到不同队列，队列绑定的消费者接收并消费消息。
     **/
    public void direct(){
        String message = "路由模式";
        System.out.println("生产者：" + message);
        // 生产者发布消息到交换机
        //参数
        // 1、交换机名称
        // 2、路由key 只给routeKey是 email、wechat 发送消息
        // 3、发送mq消息
        rabbitTemplate.convertAndSend("directExchange","email" ,message);
        rabbitTemplate.convertAndSend("directExchange","wechat" ,message);
    }

    /**
     * 通配符模式 / topic模式
     * 角色:一个生产者、多个消费者、多个队列、一个交换机;
     * 流程:两个消费者同时绑定到不同的队列上去，两个队列通过路由键匹配规则绑定到交换机上去，
     *      生产者发送消息到交换机，交换机通过路由键匹配规则转发到不同队列，队列绑定的消费者接收并消费消息。
     **/
    public void wildcard(){

    }

    public void send(String exchange, String routingKey, RabbitData data, int delay) {
        rabbitTemplate.convertAndSend(exchange,routingKey,data,(d)->{
            d.getMessageProperties().setDelay(delay);

            return d;
        },new CorrelationData(data.getUuid()));
    }

    public void refTest() {
        MqPushMainDto dto = new MqPushMainDto();
        dto.setRefCodeNo("1111");
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        System.out.println(" [ RabbitMq 推送数据 ] Sent ==> '" + dto + "'");
        System.out.println(" [ RabbitMq 推送数据 ] Sent ==> '" + JSON.toJSONString(dto) + "'");

        rabbitTemplate.convertAndSend("dh-basedata-refDataSync", "", JSON.toJSONString(dto), correlationData);
    }


    public void callback() {
        // 全局唯一
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        String message = "Hello world!";
        System.out.println(" [ 生产者 ] Sent ==> '" + message + "'");
        rabbitTemplate.convertAndSend("directExchange", "email", message, correlationData);
    }
    public void callback2() {
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        String message = "Hello world!";
        System.out.println(" [ 生产者 ] Sent ==> '" + message + "'");
        rabbitTemplate.convertAndSend("不存在的交换机", "email", message, correlationData);
    }

    public void callback3() {
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        String message = "Hello world!";
        System.out.println(" [ 生产者 ] Sent ==> '" + message + "'");
        rabbitTemplate.convertAndSend("directExchange", "不存在的路由键", message, correlationData);
    }
}
